package mainTest;

import test1.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * java的反射的使用
 * 相对C#来说语法是简单了些，主要是配置比较麻烦的说
 */
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class clazz = Class.forName("test1.Student");


        //1.反射方式获取空参构造方法
        Student student1 = (Student) clazz.newInstance();
        System.out.println(student1);
        Constructor con1 = clazz.getConstructor();
        Student student2 = (Student) con1.newInstance();
        System.out.println(student2);
        //1.2获取有参构造方法
        Constructor con2 = clazz.getConstructor(String.class, int.class, String.class);
        Student student3 = (Student) con2.newInstance("刘瑞祺", 10, "1001");
        System.out.println(student3);

        //2.反射获取私有成员变量并修改
        Constructor con3 = clazz.getConstructor(String.class, int.class, String.class);
        Student student4 = (Student) con3.newInstance("刘瑞祺", 10, "1001");
        Object obj1 = con3.newInstance("刘瑞祺", 10, "1001");
        Field name = clazz.getDeclaredField("id");
        //私有变量需要设置为可接近
        name.setAccessible(true);
        //name.set(student4,"1002");
        name.set(obj1, "1002");
        System.out.println(obj1);
        //2.2反射获取公有成员变量并修改
        Constructor con4 = clazz.getConstructor(String.class);
        Student student5 = (Student) con4.newInstance("12.4");
        Field score = clazz.getField("score");
        score.set(student5, "99");
        System.out.println(student5);
        Constructor con5 = clazz.getConstructor(String.class, int.class, String.class, String.class);
        Student student6 = (Student) con5.newInstance("liuruiqi", 23, "1001", "23.5");
        Field score2 = clazz.getField("score");
        score2.set(student6, "100");
        System.out.println(student6);

        //3.反射调用成员方法
        Constructor con7 = clazz.getConstructor();
        Student student7 = (Student) con7.newInstance();
        Method m = clazz.getMethod("eat");
        m.invoke(student7);
        Method m2 = clazz.getMethod("eat", String.class);
        m2.invoke(student7, "你");
        //调用静态方法
        Method m3 = clazz.getMethod("staticMethod");
        m3.invoke(null);
        //调用私有成员方法
        Constructor con8 = clazz.getConstructor();
        Object obj2 = con8.newInstance();
        Method m4 = clazz.getDeclaredMethod("privateMethod");
        //私有方法需要设置为可以调用，否则会报错
        m4.setAccessible(true);
        m4.invoke(obj2);
        //获取所有成员变量
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            System.out.println(fields[i]);
        }
        //获取所有方法
        Method[] methods = clazz.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) {
            System.out.println(methods[i]);
        }
    }
}
